package cn.hty.mymsg.cron.xxl.service;

import cn.hty.mymsg.common.enums.RespStatusEnum;
import cn.hty.mymsg.common.vo.BasicResultVO;
import cn.hty.mymsg.cron.xxl.constants.XxlJobConstant;
import cn.hty.mymsg.cron.xxl.entity.XxlJobGroup;
import cn.hty.mymsg.cron.xxl.entity.XxlJobInfo;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.google.common.base.Throwables;
import com.xxl.job.core.biz.model.ReturnT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import cn.hutool.http.HttpResponse;

import java.net.HttpCookie;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Slf4j
@Service
public class CronTaskServiceImpl implements CronTaskService{
    @Value("${xxl.job.admin.username}")
    private String xxlUserName;

    @Value("${xxl.job.admin.password}")
    private String xxlPassword;

    @Value("${xxl.job.admin.addresses}")
    private String xxlAddresses;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public BasicResultVO saveCronTask(XxlJobInfo xxlJobInfo) {
        //构造参数和路径
        Map<String, Object> params = JSON.parseObject(JSON.toJSONString(xxlJobInfo), new TypeReference<Map<String, Object>>() {});
        String path = Objects.isNull(xxlJobInfo.getId()) ? xxlAddresses + XxlJobConstant.INSERT_URL
                : xxlAddresses + XxlJobConstant.UPDATE_URL;
        //发送请求
        HttpResponse httpResponse;
        ReturnT returnT=null;
        try {
            httpResponse = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
            returnT=JSON.parseObject(httpResponse.body(), ReturnT.class);
            //保存则返回任务id,更新不用
            if (httpResponse.isOk()&&path.contains(XxlJobConstant.INSERT_URL)){
                Integer taskId = Integer.parseInt(String.valueOf(returnT.getContent()));
                return BasicResultVO.success(taskId);
            }else if (path.contains(XxlJobConstant.UPDATE_URL)) {
                return BasicResultVO.success();
            }
        } catch (NumberFormatException e) {
            log.error("CronTaskService#saveTask fail,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
                    , JSON.toJSONString(xxlJobInfo), JSON.toJSONString(returnT));
        }
        invalidateCookie();
        return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(returnT));
    }

    @Override
    public BasicResultVO deleteCronTask(Integer taskId) {
        String path=xxlAddresses+XxlJobConstant.DELETE_URL;
        HashMap<String,Object>params=MapUtil.newHashMap();
        params.put("id",taskId);
        HttpResponse response;
        ReturnT returnT=null;
        try {
            response = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
            returnT = JSON.parseObject(response.body(), ReturnT.class);
            if (response.isOk() && ReturnT.SUCCESS_CODE == returnT.getCode()) {
                return BasicResultVO.success();
            }
        } catch (Exception e) {
            log.error("CronTaskService#deleteCronTask fail,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
                    , JSON.toJSONString(params), JSON.toJSONString(returnT));
        }
        invalidateCookie();
        return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(returnT));
    }

    @Override
    public BasicResultVO startCronTask(Integer taskId) {
        String path=xxlAddresses+XxlJobConstant.RUN_URL;
        HashMap<String,Object>params=MapUtil.newHashMap();
        params.put("id",taskId);
        HttpResponse httpResponse;
        ReturnT returnT=null;
        try {
            httpResponse = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
            returnT=JSON.parseObject(httpResponse.body(),ReturnT.class);
            if (ReturnT.SUCCESS_CODE==returnT.getCode()&&httpResponse.isOk()){
                return BasicResultVO.success();
            }
        } catch (Exception e) {
            log.error("CronTaskService#startCronTask fail,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
                    , JSON.toJSONString(params), JSON.toJSONString(returnT));
        }
        invalidateCookie();
        return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(returnT));
    }

    @Override
    public BasicResultVO stopCronTask(Integer taskId) {
        String path = xxlAddresses + XxlJobConstant.STOP_URL;

        HashMap<String, Object> params = MapUtil.newHashMap();
        params.put("id", taskId);

        HttpResponse response;
        ReturnT returnT = null;
        try {
            response = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
            returnT = JSON.parseObject(response.body(), ReturnT.class);
            if (response.isOk() && ReturnT.SUCCESS_CODE == returnT.getCode()) {
                return BasicResultVO.success();
            }
        } catch (Exception e) {
            log.error("CronTaskService#stopCronTask fail,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
                    , JSON.toJSONString(params), JSON.toJSONString(returnT));
        }
        invalidateCookie();
        return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(returnT));
    }

    @Override
    public BasicResultVO<Integer> getGroupId(String appName, String title) {
        String path=xxlAddresses + XxlJobConstant.JOB_GROUP_PAGE_LIST;
        HashMap<String,Object>params=new HashMap<>();
        params.put("appname", appName);
        params.put("title", title);
        HttpResponse response = null;
        try {
            response=HttpRequest.post(path).form(params).cookie(getCookie()).execute();
            Integer id= JSON.parseObject(response.body()).getJSONArray("data").getJSONObject(0).getInteger("id");
            if (Objects.nonNull(id)&&response.isOk()){
                return BasicResultVO.success(id);
            }
        } catch (Exception e) {
            log.error("CronTaskService#getGroupId fail,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
                    , JSON.toJSONString(params),
                    response != null ? JSON.toJSONString(response.body()) : "");
        }
        invalidateCookie();
        return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR,
                response != null ? JSON.toJSONString(response.body()) : "");
    }

    @Override
    public BasicResultVO createGroup(XxlJobGroup xxlJobGroup) {
        //将xxlgroup作为参数
        Map<String,Object> params= JSON.parseObject(JSON.toJSONString(xxlJobGroup),new TypeReference<Map<String,Object>>(){});
        //构造请求路径
        String path=xxlAddresses+ XxlJobConstant.JOB_GROUP_INSERT_URL;
        HttpResponse httpResponse;
        ReturnT returnT = null;
        //发送请求
        try {
            httpResponse = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
            returnT = JSON.parseObject(httpResponse.body(), ReturnT.class);
            if (httpResponse.isOk() && ReturnT.SUCCESS_CODE == returnT.getCode()) {
                return BasicResultVO.success();
            }
        } catch (Exception e) {
            log.error("CronTaskService#createGroup fail,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
                    , JSON.toJSONString(params), JSON.toJSONString(returnT));
        }
        //清除缓存cookie
        invalidateCookie();
        return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(returnT));
    }
    /**
     * 清除缓存的 cookie
     */
    private void invalidateCookie() {
        redisTemplate.delete(XxlJobConstant.COOKIE_PREFIX + xxlUserName);
    }
    /**
     * 获取xxl cookie
     *
     * @return String
     */
    private String getCookie(){
        //先判断redis缓存中是否有，没有再通过登陆获取
        String cacheCookie = redisTemplate.opsForValue().get(XxlJobConstant.COOKIE_PREFIX + xxlUserName);
        if (StrUtil.isNotBlank(cacheCookie)){
            return cacheCookie;
        }
        Map<String, Object> params = MapUtil.newHashMap();
        params.put("userName", xxlUserName);
        params.put("password", xxlPassword);
        params.put("randomCode", IdUtil.fastSimpleUUID());
        String path=xxlAddresses+XxlJobConstant.LOGIN_URL;
        HttpResponse httpResponse=null;
        try {

            httpResponse= HttpRequest.post(path).form(params).execute();
            if (httpResponse.isOk()){
                List<HttpCookie> cookies = httpResponse.getCookies();
                StringBuilder sb=new StringBuilder();
                for (HttpCookie cookie : cookies) {
                    sb.append(cookie);
                }
                redisTemplate.opsForValue().set(XxlJobConstant.COOKIE_PREFIX + xxlUserName, sb.toString());
                return sb.toString();
            }
        } catch (Exception e) {
            log.error("CronTaskService#createGroup getCookie,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
                    , JSON.toJSONString(params), JSON.toJSONString(httpResponse));
        }
        return null;
    }
}
